#include "MethodTable.h"
#include <vector>

using namespace std;

InterestMethodTableEntry* InterestMethodTable;
static vector<InterestMethodTableEntry> imti;

static bool callbackMethod_ObjectWaitEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ObjectWait,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ObjectWaitExit(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ObjectWaited,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ObjectNotifyEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ObjectNotify,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ObjectNotifyAllEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ObjectNotifyAll,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ThreadStartEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ThreadStart,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ThreadJoinEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ThreadJoin,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ThreadJoinExit(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ThreadJoined,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ThreadSleepEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ThreadSleep,%08X", threadHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_ThreadSleepExit(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("ThreadSlept,%08X", threadHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_SemaphoreAcquireEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("SemaphoreAcquire,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_SemaphoreAcquireExit(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("SemaphoreAcquired,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

static bool callbackMethod_SemaphoreReleaseEntry(jthread thread, jint threadHash, jobject instance, jint instanceHash)
{
	LogEvents->BeginRecord("SemaphoreRelease,%08X,%08X", threadHash, instanceHash);
	DumpCallStack(thread, true);
	LogEvents->EndRecord();
	return false;
}

void InitInterestMethodTable()
{
	InterestMethodTableEntry ent;

	// object
	ent.ClassSignature = "Ljava/lang/Object;";
	ent.Name = "wait";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ObjectWaitEntry;
	ent.CallbackExit = callbackMethod_ObjectWaitExit;
	imti.push_back(ent);

	ent.ClassSignature = "Ljava/lang/Object;";
	ent.Name = "notify";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ObjectNotifyEntry;
	ent.CallbackExit = NULL;
	imti.push_back(ent);

	ent.ClassSignature = "Ljava/lang/Object;";
	ent.Name = "notifyAll";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ObjectNotifyAllEntry;
	ent.CallbackExit = NULL;
	imti.push_back(ent);

	// threads
	ent.ClassSignature = "Ljava/lang/Thread;";
	ent.Name = "start";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ThreadStartEntry;
	ent.CallbackExit = NULL;
	imti.push_back(ent);

	ent.ClassSignature = "Ljava/lang/Thread;";
	ent.Name = "join";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ThreadJoinEntry;
	ent.CallbackExit = callbackMethod_ThreadJoinExit;
	imti.push_back(ent);

	ent.ClassSignature = "Ljava/lang/Thread;";
	ent.Name = "sleep";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_ThreadSleepEntry;
	ent.CallbackExit = callbackMethod_ThreadSleepExit;
	imti.push_back(ent);

	// semaphore
	ent.ClassSignature = "Ljava/util/concurrent/Semaphore;";
	ent.Name = "acquire";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_SemaphoreAcquireEntry;
	ent.CallbackExit = callbackMethod_SemaphoreAcquireExit;
	imti.push_back(ent);

	ent.ClassSignature = "Ljava/util/concurrent/Semaphore;";
	ent.Name = "release";
	ent.Signature = NULL;
	ent.CallbackEntry = callbackMethod_SemaphoreReleaseEntry;
	ent.CallbackExit = NULL;
	imti.push_back(ent);


	// end
	ent.ClassSignature = NULL;
	ent.Name = NULL;
	ent.Signature = NULL;
	ent.CallbackEntry = NULL;
	ent.CallbackExit = NULL;
	imti.push_back(ent);
	InterestMethodTable = &imti[0];
}
